# -*- coding: utf-8 -*-
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

# 设置中文显示
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号

# 读取数据
data = pd.read_excel('数据集0727.xlsx')



# 检测和清除字符串列中的不可见字符（零宽字符等）
def clean_invisible_chars(df):
    # 需要清除的不可见字符列表
    invisible_chars = {
        '\u200b': '零宽空格',
        '\u200c': '零宽非连接符',
        '\u200d': '零宽连接符',
        '\u200e': '从左至右标记',
        '\u200f': '从右至左标记',
        '\ufeff': '零宽不换行空格',
        '\u2060': '单词连接符',
        '\u2061': '函数应用',
        '\u2062': '不可见乘号',
        '\u2063': '不可见分隔符',
        '\u2064': '不可见加号'
    }
    
    # 清理报告
    cleaning_report = {}
    
    # 对所有对象类型的列应用清理
    for col in df.select_dtypes(include=['object']).columns:
        # 保存清理前的唯一值数量和值
        before_values = df[col].unique()
        before_count = len(before_values)
        
        # 检测每个不可见字符
        char_found = {}
        for char, char_name in invisible_chars.items():
            # 检查该列中是否存在此不可见字符
            has_char = df[col].astype(str).str.contains(char).any()
            if has_char:
                # 计算包含此字符的值的数量
                count = df[col].astype(str).str.contains(char).sum()
                char_found[char] = {'名称': char_name, '数量': count}
        
        # 如果发现不可见字符，进行清理
        if char_found:
            # 保存原始数据的副本，用于比较
            original_values = df[col].copy()
            
            # 清理不可见字符
            for char in invisible_chars.keys():
                df[col] = df[col].astype(str).str.replace(char, '')
            
            # 清理后的唯一值
            after_values = df[col].unique()
            after_count = len(after_values)
            
            # 找出清理前后发生变化的值
            changed_values = []
            for orig_val in original_values:
                if orig_val != 'nan' and isinstance(orig_val, str):
                    cleaned_val = orig_val
                    for char in invisible_chars.keys():
                        cleaned_val = cleaned_val.replace(char, '')
                    
                    if orig_val != cleaned_val:
                        # 使用repr显示不可见字符的编码
                        changed_values.append({
                            '原值': repr(orig_val),
                            '清理后': repr(cleaned_val)
                        })
            
            # 添加到报告
            cleaning_report[col] = {
                '清理前唯一值数量': before_count,
                '清理后唯一值数量': after_count,
                '发现的不可见字符': char_found,
                '变化的值': changed_values
            }
    
    # 打印清理报告
    if cleaning_report:
        print('\n===== 不可见字符清理报告 =====')
        for col, report in cleaning_report.items():
            print(f'\n列: {col}')
            print(f'  清理前唯一值数量: {report["清理前唯一值数量"]}')
            print(f'  清理后唯一值数量: {report["清理后唯一值数量"]}')
            
            if report['发现的不可见字符']:
                print('  发现的不可见字符:')
                for char, info in report['发现的不可见字符'].items():
                    print(f'    - {repr(char)} ({info["名称"]}): {info["数量"]}个值中发现')
            
            if report['变化的值']:
                print('  变化的值示例 (最多显示5个):')
                for i, change in enumerate(report['变化的值'][:5]):
                    print(f'    - 原值: {change["原值"]}')
                    print(f'      清理后: {change["清理后"]}')
                
                if len(report['变化的值']) > 5:
                    print(f'    ... 还有 {len(report["变化的值"]) - 5} 个值发生变化')
    else:
        print('\n未发现需要清理的不可见字符')
    
    return df

# 应用清理函数
print('\n检测和清理不可见字符...')
data = clean_invisible_chars(data)

print('已完成不可见字符清理')

# 基本信息
print('数据集形状:', data.shape)
print('\n列名:', list(data.columns))
print('\n数据类型:\n', data.dtypes)
print('\n缺失值统计:\n', data.isnull().sum())

# 查看前几行数据
print('\n数据前5行:')
print(data.head().to_string())

# 统计唯一值
print('\n唯一值统计:')
for col in ['高分子基体（缩写）', '无机添加剂（缩写）', '其余材料', '加工方法', '太阳反射率', '红外发射率']:
    print(f'{col}: {data[col].nunique()} 个唯一值')
    if col not in ['太阳反射率', '红外发射率']:
        # 获取唯一值并排序，以便更容易比较
        unique_values = sorted(data[col].unique())
        print(f'{col}的唯一值 ({len(unique_values)}个):')
        # 分行打印每个唯一值，并显示其长度，便于发现潜在问题
        for val in unique_values:
            if isinstance(val, str):
                print(f'  - "{val}" (长度: {len(val)})')
            else:
                print(f'  - {val}')
        print()

# 检查数值列的统计信息
print('\n数值列统计:')
try:
    # 尝试将太阳反射率和红外发射率转换为数值类型
    data['太阳反射率'] = pd.to_numeric(data['太阳反射率'], errors='coerce')
    data['红外发射率'] = pd.to_numeric(data['红外发射率'], errors='coerce')
    
    print('太阳反射率统计:\n', data['太阳反射率'].describe())
    print('红外发射率统计:\n', data['红外发射率'].describe())
except Exception as e:
    print(f'转换数值时出错: {e}')

# 保存分析结果
with open('data_analysis_result.txt', 'w', encoding='utf-8') as f:
    f.write(f'数据集形状: {data.shape}\n')
    f.write(f'列名: {list(data.columns)}\n')
    f.write(f'缺失值统计:\n{data.isnull().sum()}\n')
    
    f.write('\n唯一值统计:\n')
    for col in ['高分子基体（缩写）', '无机添加剂（缩写）', '其余材料', '加工方法', '太阳反射率', '红外发射率']:
        f.write(f'{col}: {data[col].nunique()} 个唯一值\n')

# 可视化
try:
    # 创建一个图形，包含多个子图
    plt.figure(figsize=(15, 12))
    
    # 1. 缺失值热图
    plt.subplot(2, 2, 1)
    sns.heatmap(data.isnull(), cbar=False, cmap='viridis', yticklabels=False)
    plt.title('缺失值分布热图')
    plt.tight_layout()
    
    # 2. 太阳反射率分布
    plt.subplot(2, 2, 2)
    sns.histplot(data['太阳反射率'].dropna(), kde=True)
    plt.title('太阳反射率分布')
    
    # 3. 红外发射率分布
    plt.subplot(2, 2, 3)
    sns.histplot(data['红外发射率'].dropna(), kde=True)
    plt.title('红外发射率分布')
    
    # 4. 太阳反射率与红外发射率的关系
    plt.subplot(2, 2, 4)
    sns.scatterplot(x='太阳反射率', y='红外发射率', data=data)
    plt.title('太阳反射率与红外发射率的关系')
    
    plt.tight_layout()
    plt.savefig('data_visualization.png', dpi=300, bbox_inches='tight')
    print('\n可视化图表已保存为 data_visualization.png')
except Exception as e:
    print(f'可视化时出错: {e}')